package com.espeaker.sdk.utils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.MessageDigest;

import android.app.AlertDialog.Builder;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;

import com.espeaker.sdk.ESpeakerParameters;

public class Utility {
	private static char[] encodes = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
			.toCharArray();
	private static byte[] decodes = new byte[256];

	public static Bundle parseUrl(String url) {
		try {
			URL u = new URL(url);
			System.out.println("url:" + url);
			String query = u.getQuery();
			System.out.println("query:" + query);
			Bundle b = decodeUrl(query);
			String ref = u.getRef();
			System.out.println("ref:" + ref);
			b.putAll(decodeUrl(ref));
			return b;
		} catch (MalformedURLException e) {
			return new Bundle();
		}
	}

	public static Bundle decodeUrl(String s) {
		Bundle params = new Bundle();
		if (s != null) {
			String array[] = s.split("&");
			for (String parameter : array) {
				String v[] = parameter.split("=");
				params.putString(URLDecoder.decode(v[0]), URLDecoder
						.decode(v[1]));
			}
		}
		return params;
	}

	public static String encodeUrl(ESpeakerParameters parameters) {
		if (parameters == null) {
			return "";
		}

		StringBuilder sb = new StringBuilder();
		boolean first = true;
		for (int loc = 0; loc < parameters.size(); loc++) {
			if (first) {
				first = false;
			} else {
				sb.append("&");
			}
			String _key = parameters.getKey(loc);
			String _value = parameters.getValue(_key).toString();
			if (_value == null) {
				Log.i("encodeUrl", "key:" + _key + " 's value is null");
			} else {
				sb.append(URLEncoder.encode(parameters.getKey(loc)) + "="
						+ URLEncoder.encode(parameters.getValue(loc).toString()));
			}

		}
		return sb.toString();
	}

	public static String encodeParameters(ESpeakerParameters httpParams) {
		if (null == httpParams || isBundleEmpty(httpParams)) {
			return "";
		}
		StringBuilder buf = new StringBuilder();
		int j = 0;
		for (int loc = 0; loc < httpParams.size(); loc++) {
			String key = httpParams.getKey(loc);
			if (j != 0) {
				buf.append("&");
			}
			try {
				buf.append(URLEncoder.encode(key, "UTF-8")).append("=").append(
						URLEncoder.encode(httpParams.getValue(key).toString(), "UTF-8"));
			} catch (java.io.UnsupportedEncodingException neverHappen) {
			}
			j++;
		}
		return buf.toString();

	}

	public static void showAlert(Context context, String title, String text) {
		Builder alertBuilder = new Builder(context);
		alertBuilder.setTitle(title);
		alertBuilder.setMessage(text);
		alertBuilder.create().show();
	}

	private static boolean isBundleEmpty(ESpeakerParameters bundle) {
		if (bundle == null || bundle.size() == 0) {
			return true;
		}
		return false;
	}

	/**
	 * 将data编码成Base62的字符串
	 * 
	 * @param data
	 * @return
	 */
	public static String encodeBase62(byte[] data) {
		StringBuffer sb = new StringBuffer(data.length * 2);
		int pos = 0, val = 0;
		for (int i = 0; i < data.length; i++) {
			val = (val << 8) | (data[i] & 0xFF);
			pos += 8;
			while (pos > 5) {
				char c = encodes[val >> (pos -= 6)];
				sb.append(
				/**/c == 'i' ? "ia" :
				/**/c == '+' ? "ib" :
				/**/c == '/' ? "ic" : c);
				val &= ((1 << pos) - 1);
			}
		}
		if (pos > 0) {
			char c = encodes[val << (6 - pos)];
			sb.append(
			/**/c == 'i' ? "ia" :
			/**/c == '+' ? "ib" :
			/**/c == '/' ? "ic" : c);
		}
		return sb.toString();
	}

	/**
	 * 将字符串解码成byte数组
	 * 
	 * @param data
	 * @return
	 */
	public static byte[] decodeBase62(String string) {
		if (string == null) {
			return null;
		}
		char[] data = string.toCharArray();
		ByteArrayOutputStream baos = new ByteArrayOutputStream(string
				.toCharArray().length);
		int pos = 0, val = 0;
		for (int i = 0; i < data.length; i++) {
			char c = data[i];
			if (c == 'i') {
				c = data[++i];
				c =
				/**/c == 'a' ? 'i' :
				/**/c == 'b' ? '+' :
				/**/c == 'c' ? '/' : data[--i];
			}
			val = (val << 6) | decodes[c];
			pos += 6;
			while (pos > 7) {
				baos.write(val >> (pos -= 8));
				val &= ((1 << pos) - 1);
			}
		}
		return baos.toByteArray();
	}

	private static boolean deleteDependon(File file, int maxRetryCount) {
		int retryCount = 1;
		maxRetryCount = (maxRetryCount < 1) ? 5 : maxRetryCount;
		boolean isDeleted = false;

		if (file != null) {
			while ((!(isDeleted)) && (retryCount <= maxRetryCount)
					&& (file.isFile()) && (file.exists()))
				if (!((isDeleted = file.delete()))) {
					// LogUtils.i(file.getAbsolutePath() + "删除失败，失败次数为:" +
					// retryCount);
					++retryCount;
				}

		}

		return isDeleted;
	}

	private static void mkdirs(File dir_) {
		if (dir_ == null) {
			return;
		}
		if ((!(dir_.exists())) && (!(dir_.mkdirs())))
			throw new RuntimeException("fail to make " + dir_.getAbsolutePath());
	}

	private static void createNewFile(File file_) {
		if (file_ == null) {
			return;
		}
		if (!(__createNewFile(file_)))
			throw new RuntimeException(file_.getAbsolutePath()
					+ " doesn't be created!");
	}

	private static void delete(File f) {
		if ((f != null) && (f.exists()) && (!(f.delete()))) {
			throw new RuntimeException(f.getAbsolutePath()
					+ " doesn't be deleted!");
		}

	}

	private static boolean __createNewFile(File file_) {
		if (file_ == null) {
			return false;
		}
		makesureParentExist(file_);
		if (file_.exists())
			delete(file_);
		try {
			return file_.createNewFile();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return false;
	}

	private static boolean deleteDependon(String filepath, int maxRetryCount) {
		if (TextUtils.isEmpty(filepath))
			return false;
		return deleteDependon(new File(filepath), maxRetryCount);
	}

	private static boolean deleteDependon(String filepath) {
		return deleteDependon(filepath, 0);
	}

	private static boolean doesExisted(File file) {
		return ((file != null) && (file.exists()));
	}

	private static boolean doesExisted(String filepath) {
		if (TextUtils.isEmpty(filepath))
			return false;
		return doesExisted(new File(filepath));
	}

	private static void makesureParentExist(File file_) {
		if (file_ == null) {
			return;
		}
		File parent = file_.getParentFile();
		if ((parent != null) && (!(parent.exists())))
			mkdirs(parent);
	}

	// private static void makesureParentExist(String filepath)
	// {
	// if(filepath==null){
	// return;
	// }
	// makesureParentExist(new File(filepath));
	// }
	private static void makesureFileExist(File file) {
		if (file == null)
			return;
		if (!(file.exists())) {
			makesureParentExist(file);
			createNewFile(file);
		}
	}

	private static void makesureFileExist(String filePath_) {
		if (filePath_ == null)
			return;
		makesureFileExist(new File(filePath_));
	}

	// 判断当前网络是否为wifi
	public static boolean isWifi(Context mContext) {
		ConnectivityManager connectivityManager = (ConnectivityManager) mContext
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
		if (activeNetInfo != null
				&& activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI) {
			return true;
		}
		return false;
	}

	public static String md5(String text) {
		if (text == null)
			return null;
		StringBuffer hexString = new StringBuffer();
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(text.getBytes());
			byte[] digest = md.digest();
			for (int i = 0; i < digest.length; i++) {
				String digit = Integer.toHexString(0xFF & digest[i]);
				if (digit.length() < 2) {
					digit = "0" + digit;
				}
				hexString.append(digit);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return hexString.toString();// 32 digits
		// return hexString.toString().substring(8,24);//16 digits
	}

	/**
	 * 上传图片的策略
	 * 
	 * @author SinaDev
	 * 
	 */
	public static final class UploadImageUtils {
		private static void revitionImageSizeHD(String picfile, int size,
				int quality) throws IOException {
			if (size <= 0) {
				throw new IllegalArgumentException(
						"size must be greater than 0!");
			}
			if (!doesExisted(picfile)) {
				throw new FileNotFoundException(picfile == null ? "null"
						: picfile);
			}

			if (!BitmapHelper.verifyBitmap(picfile)) {
				throw new IOException("");
			}

			int photoSizesOrg = 2 * size;
			FileInputStream input = new FileInputStream(picfile);
			final BitmapFactory.Options opts = new BitmapFactory.Options();
			opts.inJustDecodeBounds = true;
			BitmapFactory.decodeStream(input, null, opts);
			try {
				input.close();
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}

			int rate = 0;
			for (int i = 0;; i++) {
				if ((opts.outWidth >> i <= photoSizesOrg && (opts.outHeight >> i <= photoSizesOrg))) {
					rate = i;
					break;
				}
			}

			opts.inSampleSize = (int) Math.pow(2, rate);
			opts.inJustDecodeBounds = false;

			Bitmap temp = safeDecodeBimtapFile(picfile, opts);

			if (temp == null) {
				throw new IOException("Bitmap decode error!");
			}

			deleteDependon(picfile);
			makesureFileExist(picfile);

			int org = temp.getWidth() > temp.getHeight() ? temp.getWidth()
					: temp.getHeight();
			float rateOutPut = size / (float) org;

			if (rateOutPut < 1) {
				Bitmap outputBitmap;
				while (true) {
					try {
						outputBitmap = Bitmap.createBitmap(((int) (temp
								.getWidth() * rateOutPut)), ((int) (temp
								.getHeight() * rateOutPut)),
								Bitmap.Config.ARGB_8888);
						break;
					} catch (OutOfMemoryError e) {
						System.gc();
						rateOutPut = (float) (rateOutPut * 0.8);
					}
				}
				if (outputBitmap == null) {
					temp.recycle();
				}
				Canvas canvas = new Canvas(outputBitmap);
				Matrix matrix = new Matrix();
				matrix.setScale(rateOutPut, rateOutPut);
				canvas.drawBitmap(temp, matrix, new Paint());
				temp.recycle();
				temp = outputBitmap;
			}
			final FileOutputStream output = new FileOutputStream(picfile);
			if (opts != null && opts.outMimeType != null
					&& opts.outMimeType.contains("png")) {
				temp.compress(Bitmap.CompressFormat.PNG, quality, output);
			} else {
				temp.compress(Bitmap.CompressFormat.JPEG, quality, output);
			}
			try {
				output.close();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			temp.recycle();
		}

		private static void revitionImageSize(String picfile, int size,
				int quality) throws IOException {
			if (size <= 0) {
				throw new IllegalArgumentException(
						"size must be greater than 0!");
			}

			if (!doesExisted(picfile)) {
				throw new FileNotFoundException(picfile == null ? "null"
						: picfile);
			}

			if (!BitmapHelper.verifyBitmap(picfile)) {
				throw new IOException("");
			}

			FileInputStream input = new FileInputStream(picfile);
			final BitmapFactory.Options opts = new BitmapFactory.Options();
			opts.inJustDecodeBounds = true;
			BitmapFactory.decodeStream(input, null, opts);
			try {
				input.close();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			int rate = 0;
			for (int i = 0;; i++) {
				if ((opts.outWidth >> i <= size)
						&& (opts.outHeight >> i <= size)) {
					rate = i;
					break;
				}
			}

			opts.inSampleSize = (int) Math.pow(2, rate);
			opts.inJustDecodeBounds = false;

			Bitmap temp = safeDecodeBimtapFile(picfile, opts);

			if (temp == null) {
				throw new IOException("Bitmap decode error!");
			}

			deleteDependon(picfile);
			makesureFileExist(picfile);
			final FileOutputStream output = new FileOutputStream(picfile);
			if (opts != null && opts.outMimeType != null
					&& opts.outMimeType.contains("png")) {
				temp.compress(Bitmap.CompressFormat.PNG, quality, output);
			} else {
				temp.compress(Bitmap.CompressFormat.JPEG, quality, output);
			}
			try {
				output.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
			temp.recycle();
		}

		public static boolean revitionPostImageSize(String picfile) {
			try {
				revitionImageSizeHD(picfile, 1600, 75);
				// if(Weibo.isWifi){
				// revitionImageSizeHD(picfile, 1600 , 75);
				// }
				// else{
				// revitionImageSize( picfile, 1024 , 75);
				// }

				return true;
			} catch (IOException e) {
				e.printStackTrace();
			}
			return false;
		}

		/**
		 * 如果加载时遇到OutOfMemoryError,则将图片加载尺寸缩小一半并重新加载
		 * 
		 * @param bmpFile
		 * @param opts
		 *            注意：opts.inSampleSize 可能会被改变
		 * @return
		 */
		private static Bitmap safeDecodeBimtapFile(String bmpFile,
				BitmapFactory.Options opts) {
			BitmapFactory.Options optsTmp = opts;
			if (optsTmp == null) {
				optsTmp = new BitmapFactory.Options();
				optsTmp.inSampleSize = 1;
			}

			Bitmap bmp = null;
			FileInputStream input = null;

			final int MAX_TRIAL = 5;
			for (int i = 0; i < MAX_TRIAL; ++i) {
				try {
					input = new FileInputStream(bmpFile);
					bmp = BitmapFactory.decodeStream(input, null, opts);
					try {
						input.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
					break;
				} catch (OutOfMemoryError e) {
					e.printStackTrace();
					optsTmp.inSampleSize *= 2;
					try {
						input.close();
					} catch (IOException e1) {
						e1.printStackTrace();
					}
				} catch (FileNotFoundException e) {
					break;
				}
			}

			return bmp;
		}
	}

}
